#pragma once
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <memory>
#include "Logger.hpp"
#include "Common.hpp"
#include "InetAddr.hpp"

const static int defaultfd = -1;
const static int backlog = 5;

class EchoServer
{
private:
    void HandlerIO(int sockfd, InetAddr client)
    {
        char buffer[1024];
        while (true)
        {
            buffer[0] = 0;
            ssize_t n = read(sockfd, buffer, sizeof(buffer)-1);
            if (n > 0)
            {
                buffer[n] = 0;
                std::string message = "server to say:";
                message += buffer;
                LOG(LogLevel::INFO) << client.ToString() << " say: " << buffer;
                write(sockfd, message.c_str(), message.size());
            }
            else if (n == 0)
            {
                LOG(LogLevel::INFO) << "client "
                                    << client.ToString() << " quit, me too, close fd: " << sockfd;
                break;
            }
            else
            {
                LOG(LogLevel::WARNING) << "read client "
                                       << client.ToString() << " error, sockfd : " << sockfd;
                break;
            }
        }
        close(sockfd);
    }

public:
    EchoServer(uint16_t port)
        : _listenfd(defaultfd), _port(port)
    {
    }
    void Init()
    {
        _listenfd = socket(AF_INET, SOCK_STREAM, 0);
        if (_listenfd < 0)
        {
            LOG(LogLevel::FATAL) << "socket创建失败";
            exit(SOCK_CREATE_ERR);
        }
        LOG(LogLevel::INFO) << "socket创建成功";
        InetAddr local(_port);
        int n = bind(_listenfd, local.Addr(), local.Len());
        if (n < 0)
        {
            LOG(LogLevel::FATAL) << "bind失败" << _listenfd;
            exit(SOCK_BIND_ERR);
        }
        LOG(LogLevel::INFO) << "bind成功";
        int m = listen(_listenfd, backlog);
        if (m < 0)
        {
            LOG(LogLevel::FATAL) << "listen失败";
            exit(SOCK_LISTEN_ERR);
        }
        LOG(LogLevel::FATAL) << "Listen成功";
    }
    void Start()
    {
        while (true)
        {
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);
            int sockfd = accept(_listenfd, (struct sockaddr *)&peer, &len);
            if (sockfd < 0)
            {
                LOG(LogLevel::WARNING) << "accept失败";
                continue;
            }
            InetAddr clientaddr(peer);
            LOG(LogLevel::INFO) << "获取新链接成功，sockfd：" << sockfd;
            HandlerIO(sockfd, clientaddr);
        }
    }
    ~EchoServer() {}

private:
    int _listenfd;
    uint16_t _port;
};